查看原文
其他

可能是目前最全的讲 ICMP 的文章了

CloudDeveloper Linux云计算网络 2021-12-21

对于 ICMP 协议,你想知道的,可能包括以下几点:

  • ICMP 是啥

  • 为啥需要 ICMP

  • ICMP 有哪些报文类型

  • ICMP 报文格式长啥样

  • 有哪些命令用了 ICMP

  • ICMP 有哪些内核参数

  • ICMP 的问题

带着这些问题,下面我们就来一一解答。

01 ICMP 是啥

ICMP,全称是 Internet Control Message Protocol,即互联网控制报文协议,所谓控制,就是通过下发指令来感知和控制网络环境,所以它一定是配合一个无法感知网络环境的协议来工作的,这个协议就是 IP(包括 IPv4 和 IPv6)。

所以,ICMP 通常被认为是 IP 协议的一部分,它封装在 IP 层中,使用 IP 协议进行传输。因此,严格来说,ICMP 既不是一个网络层协议,也不是一个传输层协议,而是介于两者之间的一个协议。

它的主要功能是传输网络诊断信息,信息主要包括两类:

  • 一类是 查询类报文 :主要用于信息的查询和采集,比如采集传输路径上的每个路由器都是谁,本次传输的报文是否达到目的地等等。

  • 另一类是 差错诊断类报文 :主要用于诊断网络故障,比如传输报文被丢弃的原因是什么等等。

02 为啥需要 ICMP

我们都知道,IP 协议是一个不可靠协议,如果 IP 包在传输过程中出现错误,比如 checksum 对不上,拥塞,超时等等,那么 IP 包是会直接被丢弃的,之后也不会有进一步的努力来修正。

这是 IP 协议的一个设计准则决定的,也就是 best effort,尽力而为,这样的好处是让 IP 协议尽量保持简单的形态,只负责有效率的数据传输,而更多的质量控制交给高层的协议去处理(比如 TCP)。

但高层能提供质量控制的协议毕竟在少数,所以就需要在下层有协议来辅助 IP 完成必要的网络质量管理。ICMP 协议自然就被提出来了。

通过 ICMP 协议,当 IP 包发生错误的时候,上层发送 IP 包的主机或路由器并不知道下层发生了错误,这个时候,下层的主机或路由器就可以通过发送 ICMP 包,将错误信息汇报给上层,从而让上层的主机或路由器进行调整。

不过需要注意的是,ICMP 仅仅只能提供某些特定类型的错误信息汇报,并不能帮助 IP 协议成为可靠的协议。它能做的事还是有限,但用于基本的网络质量管理是足够了。

03 ICMP 报文格式长啥样

如下图所示,ICMP 报文是被封装在 IP 数据报中传输的。

IP 报头中的 Protocol 字段为 1 即表示该报文携带的是 ICMP 报文。(此处只是为了说明问题,因此 IP 报头是简化了的)

进一步看,ICMP 报头为 4 个字节:

  • 类型 type:占 1 个字节,表示较大范围类型分类的 ICMP 报文

  • 代码 code:占 1 个字节,表示较小范围类型分类的 ICMP 报文(type的细分)

  • 校验和 checksum:占 2 个字节,ICMP checksum 的计算方法类似于 IP checksum,但是不同的是 IP 只校验头部,ICMP 校验头部+数据部分

后面紧接的 ICMP 数据部分,根据前面的类型和代码字段的不同,具有不同的内容。

04 ICMP 有哪些报文类型

ICMP 支持的报文类型非常多,详细看下表:

类型字段指代了一大类,代码字段又细分了几大小类。

上面可能不够明确,我们通过下面这两张表来列举一下,由于类型太多了,而且有些平时非常少见,因此,这里我们只列举常见的一些类型。

第一张表:类型表

类型内容种类解释
0应答Rping应答
3目的不可达E很多细分,如主机/协议等
4源端抑制E表示拥塞
5重定向E表示最优的路由路径
8请求Rping请求
9路由器通告R告知路由器地址
10路由器请求R请求路由器通告
11超时ETTL=0
12参数问题E有问题的报文

注:R表示查询报文,E表示差错报文

进一步,对于每种类型,又可以根据代码字段细分多种子类型,请看第二张表:

第二张表:类型细分表

类型代码内容解释
30网络不可达没有路由到目的地
31主机不可达已知但不可达的主机
32协议不可达未知的协议
33端口不可达未知的端口
34要分片但设置了不分片位路由器MTU限制需分片但无法分片
35源路由失败中间跳不可达
313管理禁止通信被过滤策略禁止的通信
314违反主机优先级src/dst/port不准许的优先级
315优先级终止生效在最小ToS之下
51主机重定向数据报指示一个可选的路由器/主机
110在传输期间时间超时跳数限制/TTL超时
111分片重组时间超时重组计时器超时之前,有分片未到达
120指针指示差错字节偏移量指示第一个问题字段
122错误的长度数据包有无效的Total Length字段

通过这两张表,每一种类型的 ICMP 包的意思应该都比较清楚了。

有一种可能不太好理解,这里再重点讲解一下:

① 源端抑制

属于差错信息。如果某个源主机向目的主机快速地发送数据包,但目的主机来不及处理,就会向源主机发出该类型的 ICMP 包,提醒源主机放慢发送速度。

② 重定向

属于差错信息。如果某个源主机向网络中发送一个 IP 包,路径中某个路由器收到这个 IP 包,对照其路由表,发现自己不应该接收该包(包需要原路返回,或者不是最佳路由路径),就会向源主机发送该类型的 ICMP 包,提醒源主机修改自己的路由表,下次路由到另外一个更好的路由器。

③ 需要分片但设置了不分片位

属于差错信息。如果某个源主机在发送一个 IP 包之前,对该 IP 包中的首部字段 DF 位设为 1,也就是“分片禁止位=1”,表示该包在传输的过程中不允许分片,但是中间某个路由器允许传输的最大路径 MTU 小于该包大小,需要分片才能传输,但是由于设置不分片位,路由器会将该包丢弃,并向源主机发送一个携带 MTU 信息的 ICMP 包,提醒源主机下次发包的大小不应超过该 MTU 的值。

这种类型的 ICMP 包通常用来发现传输路径上的 MTU 值。

④ TTL超时

属于差错信息。超时定义了数据包在网络中存活的最长时间,IPv4 中的 TTL 字段和 IPv6 中的 Hop Limit 字段都表示了这层意思,它们是一个整数值,会随着经过的路由器而递减,当减为 0 时,就认为该 IP 包超时,然后当前减为 0 的路由器会向源主机发送 ICMP 包,通知它发生了超时错误。

05 有哪些命令体现了 ICMP

ICMP 的这些包的类型,用户可以充分用来诊断网络的故障情况。

因此诞生了一些利用 ICMP 协议的网络诊断工具,其中比较知名的就是 pingtraceroute。这两工具分别利用两种类型的 ICMP 报文:

  • ping 使用查询类型报文

  • traceroute 使用差错类型报文

① ping

ping 使用了查询报文中的请求报文(类型为 8)和应答报文(类型为 0),主要查询某个网络节点的连通性,如果出现网络不连通的情况,具体是什么问题,会在应答报文中附带相关的差错信息予以告知。比如网络不可达(Network Unreacheable)、主机不可达(Host Unreachable)等等,然后用户就可以根据这些信息来分析具体是哪个环节出现问题。

下面一张图,显示了一个 ping 包的完整流程:

可以看到,通过各层协议栈的层层封装和解封装,一个 ping 包从一台主机发送到另一台主机,包括请求包和应答包。其中,如果目标 MAC 地址未知的话,需要先发出 ARP 请求拿到,然后再进行封装。

关于 ping 命令的使用案例可以参考这篇文章:ping容易忽略的10点用法和排查问题技巧

② traceroute

traceroute 是类 Linux 系统自带的工具,Windows 上类似的工具是 tracert,两者有些许不同,tracert 默认使用 ICMP 报文探测,而 traceroute 默认使用 UDP,但是也可以使用 TCP/ICMP 三种报文探测。

traceroute 利用 ICMP 差错报文,主要用来确定这几件事:

  • 确定通信双方路径上经过的路由器设备

  • 确定 UDP 包是否成功达到目的地

  • 发现路径 MTU

确定通信双方路径上经过的路由器设备 。就是利用上面提到的超时类型的 ICMP 报文来实现。traceroute 向目的地发送 IP 包,刚开始的时候,将 TTL 设置为 1,当经过第一个路由器时,TTL -1 = 0 引发超时错误,第一个路由器回复 ICMP 超时报文,源主机就可以知道路径第一个路由器的信息,随后 TTL 被设置为 2、3、4, ...,直到到达目的地,这样,沿途每个路由器都会向源主机回复 ICMP 超时报文,traceroute 就可以拿到所有的路由器信息了。

不过这里要 注意 ,并不是所有路由器都会返回 ICMP 报文,因为出于安全性考虑,大多数防火墙以及启用了防火墙功能的路由器都默认配置为不返回任何 ICMP 报文,管理员也会主动配置,所以这时使用 traceroute 就不一定能拿到所有路由器信息了。

确定 UDP 包是否成功达到目的地 。使用上面的方法能拿到路由器信息,但并不能确定发的包是否到达目的地。traceroute 通过发送 UDP 包来解决了这个问题,因为 UDP 包的可用端口号范围 <3000,所以就可以在发送 UDP 包的时候填入一个 >3000 的端口号,这样,如果当包确实到达了目的地,由于端口不匹配,就会返回一个端口不可达的 ICMP 报文,源主机就可以确定包确实到了目的地了。

发现路径 MTU 。这块在上面讲 “需要分片但设置了不分片位” 类型报文的时候已经讲过,traceroute 就是利用这种类型报文来逐一地确认传输路径上各个路由器之间的 MTU 值。

关于 traceroute 命令的使用案例可以参考这篇文章:排查网络问题,请务必掌握这款工具

③ MTR

MTR 全称 my traceroute,相对以上两个其实是更好的网络排障工具,只是用的人不多,导致它不太出名。之所以说它好,是因为它结合了 pingnslookuptraceroute 三款工具的特性。

关于 MTR 的安装和使用分析详见这篇文章:这款网络排查工具,堪称神器!

④ tcptraceroute

这块工具从名称就可以看出,是基于 TCP 的 traceroute,也就是它使用 TCP 包(具体是 TCP 的 SYN 包)来进行网络探测,而不是 ICMP 包。

从上面我们已经知道,traceroute -T 就是使用 TCP 包进行探测,所以 tcptraceroute 其实等效于 traceroute -T

使用 TCP 包进行探测的原因,主要是因为现代广泛使用的防火墙,出于安全的考虑,都会拦截 UDP 包和 ICMP 包,而通常不会拦截 TCP SYN 包。所以使用 TCP 包探测能够通过大多数的网络设备,使探测结果更加精确。

06 ICMP 有哪些内核参数

总结了下面一幅图,其中比较常用的是 net.ipv4.icmp_echo_ignore_all,这是禁 ping 的一个参数,禁 ping 有几种方法,可以参考这篇文章:Linux禁止ping以及开启ping的方法

其他的参数大家有兴趣也可以看看,遇到不懂的直接查这个图即可。

07 ICMP 的问题

ICMP 协议是 IP 协议的助手,能够为 IP 协议提供相关的故障诊断和控制信息,但 ICMP 仍然不能为 IP 提供可靠性,最常见的丢包(路由器缓冲区溢出)并不会触发任何的 ICMP 信息,只能由其他协议如 TCP 来处理这种情况。

此外,正因为 ICMP 能够查询网络设备相关的配置信息,并且使用简单,黑客们都比较青睐使用 ICMP 报文来构建攻击报文。所以很多的网络设备都会用防火墙来阻止 ICMP 报文,这让很多诊断工具,比如上面介绍的几种,都很难发挥用武之地。

常见的 ICMP 攻击是 ICMP 泛洪攻击,这是一种 DDoS 攻击。简单说就是攻击者向一个子网的的广播地址发送多个 ICMP echo 包,包的源地址伪装成他想要攻击的目的主机的 IP,然后该子网的所有主机的 ICMP reply 包都会送到被攻击主机,该主机瞬时收到大量的 ICMP 回复包,消耗大量资源,来不及处理,便会进入瘫痪或无法提供正常服务。

解决 ICMP 泛洪攻击最简单的方法就是禁 ping 了。只要禁 ping,不管黑客有多少肉机,他都无可奈何了。

当然还有更高级的攻击的方式,以及更好的防护方式,道高一尺魔高一丈,大家有兴趣可以查阅相关资料了解。


OK,以上就是今天的文章了,大家觉得不错,不烦给我个「在看」或者分享哦。



后台回复“加群”,带你进入高手如云交流群


推荐阅读:

Linux 硬盘结构长啥样,了解一下

谨慎使用的 Linux 命令

史上最硬核的Linux依赖问题解决方案

一文搞懂HTTP+TCP的长连接和短连接

正确理解CPU使用率和平均负载的关系

和面试官之间关于操作系统的一场对弈

Linux 系统 UDP 丢包问题分析思路

如何拥有一台属于自己的私有云!

晋升、面试中绕不开的性能优化问题
史上最全Linux面试题(2020最新版)

什么是物联网?这里有你需要了解的一切

Kubernetes的架构为什么是这个样的?

任何人都能看得懂的网络协议之ARP



喜欢,就给我一个“在看”



10T 技术资源大放送!包括但不限于:云计算、虚拟化、微服务、大数据、网络、Linux、Docker、Kubernetes、Python、Go、C/C++、Shell、PPT 等。在公众号内回复「1024」,即可免费获取!!

: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存